//websocket_helper.hpp
#ifndef WEBSOCKET_HELPER_H
#define WEBSOCKET_HELPER_H

#include "App.h"
#include <iostream>
#include <string>
#include <functional>
#include <unordered_map>
#include <thread>
#include <vector>
#include "thread_pool.h"
#include "object_pool.hpp"
#include <string.h>
#include <queue>
#include <vector>
#include "web_data.h"
#include "multi_memory_pool.hpp"


#define SAFE_DELETE(ptr) \
  do                     \
  {                      \
    if (ptr)             \
    {                    \
      delete (ptr);      \
    }                    \
  } while (0)


struct CustomWSData {
    CustomWSData(){}
    CustomWSData(const CustomWSData &other)
    {
      this->tWsData = other.tWsData;
    }
    ~CustomWSData(){}
    WebUserData tWsData;
    std::mutex queMtx;
    std::queue<std::string> backQueue;
};

template<bool SSL>
class HttpDataImpl : public std::enable_shared_from_this<HttpDataImpl<SSL>>, public HttpData {
public:
    HttpDataImpl()
        :isClosed(false), m_res(nullptr), m_app(nullptr) {}

    virtual ~HttpDataImpl() 
    {
      if(m_reqMemoryBlockVec.size() > 0)
      {
        MultiSizeMemoryPool::getInstance().deleteMemBlock(m_reqMemoryBlockVec);
        m_reqMemoryBlockVec.clear();
      }
    }

    void clearCache()
    {
      if(m_reqMemoryBlockVec.size() > 0)
      {
        MultiSizeMemoryPool::getInstance().deleteMemBlock(m_reqMemoryBlockVec);
        m_reqMemoryBlockVec.clear();
      }
      this->isClosed = false;
      this->m_res = nullptr;
      this->m_app = nullptr;
      this->m_reqHeaders.clear();
      this->m_httpPool = nullptr;
      //std::cout<<"===clearCache====\n";
    }

    std::unordered_map<std::string, std::string> gerReqHeader() override {
        return m_reqHeaders;
    }

    std::vector<MemBlock> getReqBody() override {
      return m_reqMemoryBlockVec;
    }

    void writeStatus(std::string respStatus) override
    {
      if(respStatus.length() <= 0)
      {
        return;
      }
      // 加入发送者线程
      std::shared_ptr<HttpDataImpl> pData = this->shared_from_this();
      uWS::HttpResponse<SSL>* res = m_res;
      m_app->getLoop()->defer([res, respStatus=std::move(respStatus), pData = std::move(pData)]() 
      {
        res->cork([res, respStatus=std::move(respStatus), pData = std::move(pData)]() 
        {
          res->writeStatus(std::string_view(respStatus));
        });
      });
    }

    void writeHeader(std::unordered_map<std::string, std::string> &respHeaders) override
    {
      if(respHeaders.size() <= 0)
      {
        return;
      }
      // 加入发送者线程
      std::shared_ptr<HttpDataImpl> pData = this->shared_from_this();
      uWS::HttpResponse<SSL>* res = m_res;
      m_app->getLoop()->defer([res, respHeaders=std::move(respHeaders), pData = std::move(pData)]() 
      {
        res->cork([res, respHeaders=std::move(respHeaders), pData = std::move(pData)]() 
        {
          // send header
          for (const auto& [key, val] : respHeaders)
          {
            res->writeHeader(std::string_view(key), std::string_view(val));
          }
        });
      });
    }

    void send(std::string respBody) override
    {
      if(respBody.size() <= 0)
      {
        return;
      }
      // 加入发送者线程
      std::shared_ptr<HttpDataImpl> pData = this->shared_from_this();
      uWS::HttpResponse<SSL>* res = m_res;
      m_app->getLoop()->defer([res, respBody=std::move(respBody), pData = std::move(pData)]() 
      {
        res->cork([res, respBody=std::move(respBody), pData = std::move(pData)]() 
        {
          res->end(std::string_view(respBody));
        });
      });
    }

    void finalize() override
    {
      // 加入发送者线程
      std::shared_ptr<HttpDataImpl> pData = this->shared_from_this();
      ObjectPool<HttpDataImpl<SSL>> *httpPool = m_httpPool;
      uWS::HttpResponse<SSL>* res = m_res;
      m_app->getLoop()->defer([res, httpPool=std::move(httpPool), pData = std::move(pData)]() 
      {
        res->cork([res, httpPool=std::move(httpPool), pData = std::move(pData)]() 
        {
          pData->clearCache();
          httpPool->release(std::move(pData));
        });
      });
    }
public:
    std::vector<MemBlock> m_reqMemoryBlockVec;
    /*发送者的数据copy*/
    bool isClosed;
    uWS::HttpResponse<SSL>* m_res;
    uWS::TemplatedApp<SSL>* m_app;
    std::unordered_map<std::string, std::string> m_reqHeaders;
    ObjectPool<HttpDataImpl<SSL>> *m_httpPool;
};


template <bool SSL>
class WsDataImpl : public std::enable_shared_from_this<WsDataImpl<SSL>>, public WsData
{
public:
  WsDataImpl() : m_bUpgradeStatus(false),isClosed(false),m_res(nullptr), m_app(nullptr), m_context(nullptr),m_ws(nullptr) {}

  virtual ~WsDataImpl()
  {
    if(m_reqMemoryBlockVec.size() > 0)
    {
      MultiSizeMemoryPool::getInstance().deleteMemBlock(m_reqMemoryBlockVec);
      m_reqMemoryBlockVec.clear();
    }
  }

  void clearCache()
  {
    if(m_reqMemoryBlockVec.size() > 0)
    {
      MultiSizeMemoryPool::getInstance().deleteMemBlock(m_reqMemoryBlockVec);
      m_reqMemoryBlockVec.clear();
    }
    this->m_bUpgradeStatus = false;
    this->m_respBody.clear();
    this->isClosed = false;
    this->m_res = nullptr;
    this->m_app = nullptr;
    this->m_context = nullptr;
    this->m_ws = nullptr;
    this->m_wsPool = nullptr;
    this->m_reqHeaders.clear();
   // std::cout<<"===clearCache====\n";
  }

  std::unordered_map<std::string, std::string> gerReqHeader()
  {
    return m_reqHeaders;
  }

  std::vector<MemBlock> getReqBody()
  {
    return m_reqMemoryBlockVec;
  }

  void upgrade(bool success)
  {
    m_bUpgradeStatus = success;
    addUpgradeCork();
  }

  WebUserData* getUserData()
  {
    //判断是否在upgrade期间
    if(m_curType == WSMethod::UPGRADE)
    {
      //std::cout<<"upgrade getUserdata\n";
      return &(m_userdata.tWsData);
    }
    return &(m_ws->getUserData()->tWsData);
  }

  void addUpgradeCork()
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::HttpResponse<SSL> *res = m_res;
    uWS::TemplatedApp<SSL> *app = m_app;
    ObjectPool<WsDataImpl<SSL>> *wsPool = m_wsPool;
    us_socket_context_t *context = std::move(m_context);
    if (pData->m_bUpgradeStatus)
    {
      if(pData->isClosed)
      {
        return;
      } 
      app->getLoop()->defer([res, wsPool, pData = std::move(pData), context=std::move(context)]()
      {
        res->cork([res, wsPool, pData = std::move(pData), context=std::move(context)]()
        {
          if(pData->isClosed)
          {
            return;
          }          
          res->template upgrade<CustomWSData>(std::move(pData->m_userdata),
            std::string_view(pData->m_reqHeaders["sec-websocket-key"]),
            std::string_view(pData->m_reqHeaders["sec-websocket-protocol"]),
            std::string_view(pData->m_reqHeaders["sec-websocket-extensions"]),
            context);

          pData->clearCache();
          wsPool->release(std::move(pData));

        }); 
      });
    }
    else
    {
      res->end(std::string_view("upgrade error"));
      //
      pData->clearCache();
      wsPool->release(std::move(pData));
    }
  }

  void addCork()
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::WebSocket<SSL, true, CustomWSData> * ws = m_ws;
    uWS::TemplatedApp<SSL>* app = m_app;
    ObjectPool<WsDataImpl<SSL>> *wsPool =m_wsPool;
    // 加入队列
    if (pData->m_respBody.length() > 0)
    {
      app->getLoop()->defer([ws, wsPool, pData = std::move(pData)]()
      { 
        ws->cork([ws, wsPool, pData = std::move(pData)]()
        {
          ws->send(std::string_view(pData->m_respBody), uWS::OpCode::TEXT);
        });
      });
    }
  }


  void send(char *pRespBody, size_t respLen) override
  {
    if (respLen > 0)
    {
      std::string copyBody(pRespBody, respLen);
      m_respBody = std::move(copyBody);
      addCork();
    }
  }

  void send(std::string respBody) override
  {
    send((char *)respBody.c_str(), respBody.length());
  }

  void subscribe(std::string topic) override
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::WebSocket<SSL, true, CustomWSData> * ws = m_ws;
    m_app->getLoop()->defer([ws, topic, pData = std::move(pData)]()
    { 
      ws->cork([ws, topic, pData = std::move(pData)]()
      {
        ws->subscribe(std::string_view(topic));
      });
    });
  }
  void unsubscribe(std::string topic) override
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::WebSocket<SSL, true, CustomWSData> * ws = m_ws;
    m_app->getLoop()->defer([ws, topic, pData = std::move(pData)]()
    { 
      ws->cork([ws, topic, pData = std::move(pData)]()
      {
        ws->unsubscribe(std::string_view(topic));
      });
    });
  }
  
  void publish(std::string topic, std::string msg) override
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::WebSocket<SSL, true, CustomWSData> * ws = m_ws;
    m_app->getLoop()->defer([ws, topic, msg, pData = std::move(pData)]()
    { 
      ws->cork([ws, topic, msg, pData = std::move(pData)]()
      {
        ws->publish(std::string_view(topic), std::string_view(msg));
      });
    });
  }

  void finalize() override
  {
    std::shared_ptr<WsDataImpl> pData = this->shared_from_this();
    uWS::WebSocket<SSL, true, CustomWSData> * ws = m_ws;
    uWS::TemplatedApp<SSL>* app = m_app;
    ObjectPool<WsDataImpl<SSL>> *wsPool =m_wsPool;
    // 加入队列
    app->getLoop()->defer([ws, wsPool, pData = std::move(pData)]()
    { 
      ws->cork([wsPool, pData = std::move(pData)]()
      {
        pData->clearCache();
        wsPool->release(std::move(pData)); 
      });
    });
  }

public:
  std::vector<MemBlock> m_reqMemoryBlockVec;
  bool m_bUpgradeStatus;
  std::string m_respBody;
  bool isClosed;
  uWS::HttpResponse<SSL> * m_res;
  uWS::TemplatedApp<SSL>* m_app;
  us_socket_context_t *m_context;
  uWS::WebSocket<SSL, true, CustomWSData> * m_ws;
  WSMethod m_curType; //1表示Upgrade,
  ObjectPool<WsDataImpl<SSL>> *m_wsPool;
  //保存upgrade期间的数据
  CustomWSData m_userdata;
  std::unordered_map<std::string, std::string> m_reqHeaders;
};


template <bool SSL>
class WebServer {
public:
    WebServer() {}

#if 0
    void multiThrdStart(int port)
     {
        std::cout << "std::thread::hardware_concurrency(): " << std::thread::hardware_concurrency() << std::endl;
        int threadNum = std::thread::hardware_concurrency();
        std::vector<std::thread*> threads(threadNum);

        std::transform(threads.begin(), threads.end(), threads.begin(), [this, port](std::thread* /*t*/) {
            return new std::thread([this,port]() { start(port); });
        });

        std::for_each(threads.begin(), threads.end(), [](std::thread* t) {
            t->join();
            SAFE_DELETE(t);
        });
    }
#endif 

    void httpHandler(uWS::HttpResponse<SSL> * res, uWS::HttpRequest *req,  std::function<void(std::shared_ptr<HttpData>)> handler, uWS::TemplatedApp<SSL>* app)
    {
        std::shared_ptr<HttpDataImpl<SSL>> pDataSharedPtr = m_httpObjectPool.acquire();
        HttpDataImpl<SSL> *pData = pDataSharedPtr.get();
        res->onAborted([pData]() {
          //std::cout << "request aborted" << std::endl;
          pData->isClosed = true;
        });
        pDataSharedPtr->m_res = res;
        pDataSharedPtr->m_app = app;
        pDataSharedPtr->m_httpPool = &m_httpObjectPool;
        // 获取头部数据
        getCustomHeaders(req, pDataSharedPtr->m_reqHeaders);
        // URL后面的数据
        auto query = req->getQuery();
        parseQuery2(std::string(query), pDataSharedPtr->m_reqHeaders);
        res->onData([handler,app, res, pDataSharedPtr=std::move(pDataSharedPtr)](std::string_view data, bool last) mutable
        {
          if(pDataSharedPtr->m_reqMemoryBlockVec.size() == 0 && pDataSharedPtr->m_reqHeaders["content-length"].length() > 0)
          {
            std::string sLength = pDataSharedPtr->m_reqHeaders["content-length"];
            size_t totalLen = std::stoull(sLength.c_str());
            MultiSizeMemoryPool::getInstance().newMemBlock(totalLen, pDataSharedPtr->m_reqMemoryBlockVec);
          }
          MultiSizeMemoryPool::getInstance().insertMemBlockData(data.data(), data.size(), pDataSharedPtr->m_reqMemoryBlockVec);

          if(last)
          {
            ThreadPool::getInstance().enqueue([handler,app, res, pDataSharedPtr=std::move(pDataSharedPtr)]() {
              if (!pDataSharedPtr->isClosed) 
              {
                handler(std::move(pDataSharedPtr));
              }
            });
          }
        });
    }

    void initConfig(WebBehaviorConfig *pConfig, int threadNum)
    {
        if(pConfig)
        {
            m_webConfig = *pConfig;
        }
        ThreadPool::getInstance(threadNum);
    }

    void start(int port)
    {
        std::thread::id threadId = std::this_thread::get_id();
        std::cout << "Current thread ID: " << threadId << std::endl;
        uWS::SocketContextOptions options;

        if constexpr (SSL) 
        {
            options.key_file_name = m_webConfig.key_file_name;
            options.cert_file_name = m_webConfig.cert_file_name;
            options.passphrase = m_webConfig.passphrase;
            options.dh_params_file_name = m_webConfig.dh_params_file_name;
            options.ca_file_name = m_webConfig.ca_file_name;
            options.ssl_ciphers = m_webConfig.ssl_ciphers;
            options.ssl_prefer_low_memory_usage = m_webConfig.ssl_prefer_low_memory_usage;

            //std::cout<<"key_file:" <<options.key_file_name<<std::endl;
            //std::cout<<"cert_file:" <<options.cert_file_name<<std::endl;
            //std::cout<<"pwd:" <<options.passphrase<<std::endl;           
        }

        uWS::TemplatedApp<SSL>* app = nullptr;
         if constexpr (SSL) 
         {
            app =  new uWS::SSLApp(options);
         } 
         else 
         {
            app =  new uWS::App();
         }

        // 循环遍历
        for (const auto& [method, handersMap] : m_handlers) 
        {
            for(const auto &[url, handler] : handersMap)
            {
                 if(!handler)
                 {
                    continue;;
                 }
                switch(method)
                {
                    case HttpMethod::GET:
                    {
                        app->get(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                    case HttpMethod::POST:
                    {
                        app->post(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                    case HttpMethod::PUT:
                    {
                        app->put(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                     case HttpMethod::DEL:
                    {
                        app->del(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                     case HttpMethod::OPTION:
                    {
                        app->options(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                     case HttpMethod::HEAD:
                    {
                        app->head(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                     case HttpMethod::PATH:
                    {
                        app->patch(url, [this, handler, app](auto *res, auto *req) {
                        httpHandler(res, req, handler, app);
                        });
                    }
                    break;
                }
                
            }
        }

                // 循环遍历
        for (const auto& [url, handersMap] : m_wsHanders) 
        {
            app->template ws<CustomWSData>(url, {
                .compression = (uWS::CompressOptions)m_webConfig.compression,
                .maxPayloadLength = m_webConfig.maxPayloadLength,
                .idleTimeout = m_webConfig.idleTimeout,
                .maxBackpressure = m_webConfig.maxBackpressure,
                .closeOnBackpressureLimit = m_webConfig.closeOnBackpressureLimit,
                .resetIdleTimeoutOnSend = m_webConfig.resetIdleTimeoutOnSend,
                .sendPingsAutomatically = m_webConfig.sendPingsAutomatically,
                .maxLifetime = m_webConfig.maxLifetime,
                .upgrade = [this, url, app](auto *res, auto *req, auto *context) {
                    auto hander = m_wsHanders[url][WSMethod::UPGRADE];
                     if(!hander)
                    {
                        return;
                    }
                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    WsDataImpl<SSL> *pData = pDataSharedPtr.get();
                    res->onAborted([pData]() {
                        //std::cout << "request aborted" << std::endl;
                        pData->isClosed = true;
                    });
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_context = std::move(context);
                    pDataSharedPtr->m_curType = WSMethod::UPGRADE;
                    pDataSharedPtr->m_res = res;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    // 获取头部数据
                    getCustomHeaders(req, pDataSharedPtr->m_reqHeaders);
                    // URL后面的数据
                    auto query = req->getQuery();
                    parseQuery2(std::string(query), pDataSharedPtr->m_reqHeaders);
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr = std::move(pDataSharedPtr)]() {
                        if (pDataSharedPtr->isClosed) 
                        {
                           return;
                        }
                        hander(std::move(pDataSharedPtr));
                    });
                   
                },
                .open = [url, app, this](auto *ws) {
                    auto hander = m_wsHanders[url][WSMethod::OPEN];
                     if(!hander)
                    {
                        return;
                    }
                    //-----add-----------
                    ws->getUserData()->tWsData.isValid = true;

                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_ws = ws; 
                    pDataSharedPtr->m_curType = WSMethod::OPEN;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr=std::move(pDataSharedPtr)]() {
                      hander(std::move(pDataSharedPtr));
                    });
                },
                .message = [this, app, url](auto *ws, std::string_view message, uWS::OpCode /*opCode*/) {
                    auto hander = m_wsHanders[url][WSMethod::MESSAGE];
                    if(!hander)
                    {
                        return;
                    }
                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    if(message.size() > 0)
                    {
                      MultiSizeMemoryPool::getInstance().newMemBlockAndInsertData(message.data(), message.size(), pDataSharedPtr->m_reqMemoryBlockVec);
                    }
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_ws = ws;
                    pDataSharedPtr->m_curType = WSMethod::MESSAGE;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr=std::move(pDataSharedPtr)]() {
                        hander(std::move(pDataSharedPtr));
                    });
                },
                .dropped = [this](auto *ws, std::string_view message, uWS::OpCode /*opCode*/) {
                  if(!m_webConfig.storeSendFailMsg)
                  {
                    return;
                  }
                  std::lock_guard<std::mutex> lock(ws->getUserData()->queMtx);
                  ws->getUserData()->backQueue.push(std::string(message)); // 将消息加入队列
                },
                .drain = [this, url, app](auto* ws) {
                  if(!m_webConfig.storeSendFailMsg)
                  {
                    return;
                  }
                  std::queue<std::string> localQueue;
                  {
                      std::lock_guard<std::mutex> lock(ws->getUserData()->queMtx);
                      std::swap(localQueue, ws->getUserData()->backQueue);
                  }

                  ThreadPool::getInstance().enqueue([app, ws, localQueue = std::move(localQueue)]() mutable {
                       app->getLoop()->defer([ws, localQueue = std::move(localQueue)]() mutable { 
                                ws->cork([ws, localQueue = std::move(localQueue)]() mutable{
                                        while (!localQueue.empty()) 
                                        {
                                          std::string message = localQueue.front();
                                          localQueue.pop();
                                          ws->send(std::string_view(message), uWS::OpCode::TEXT);
                                        }
                                        
                                         
                                    }); 
                            });
                    });
                },
                .ping = [url, app, this](auto *ws, std::string_view message) {
                    auto hander = m_wsHanders[url][WSMethod::PING];
                    if(!hander)
                    {
                      return;
                    }
                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    if(message.size() > 0)
                    {
                      MultiSizeMemoryPool::getInstance().newMemBlockAndInsertData(message.data(), message.size(), pDataSharedPtr->m_reqMemoryBlockVec);
                    }
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_ws = ws;
                    pDataSharedPtr->m_curType = WSMethod::PING;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr=std::move(pDataSharedPtr)]() {
                        hander(std::move(pDataSharedPtr));
                    });
                    
                },
                .pong = [url, app, this](auto *ws, std::string_view message) {
                    auto hander = m_wsHanders[url][WSMethod::PONG];
                    if(!hander)
                    {
                      return;
                    }
                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    if(message.size() > 0)
                    {
                      MultiSizeMemoryPool::getInstance().newMemBlockAndInsertData(message.data(), message.size(), pDataSharedPtr->m_reqMemoryBlockVec);
                    }
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_ws = ws;
                    pDataSharedPtr->m_curType = WSMethod::PONG;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr=std::move(pDataSharedPtr)]() {
                      hander(std::move(pDataSharedPtr));
                    });
                    
                },
                .close = [url, app, this](auto *ws, int /*code*/, std::string_view message) {
                    auto hander = m_wsHanders[url][WSMethod::CLOSE];
                    if(!hander)
                    {
                      return;
                    }
                    std::shared_ptr<WsDataImpl<SSL>> pDataSharedPtr = m_wsObjectPool.acquire();
                    if(message.size() > 0)
                    {
                      MultiSizeMemoryPool::getInstance().newMemBlockAndInsertData(message.data(), message.size(), pDataSharedPtr->m_reqMemoryBlockVec);
                    }
                    pDataSharedPtr->m_app = app;
                    pDataSharedPtr->m_ws = ws;
                    pDataSharedPtr->m_curType = WSMethod::CLOSE;
                    pDataSharedPtr->m_wsPool = &m_wsObjectPool;
                    ThreadPool::getInstance().enqueue([hander, pDataSharedPtr=std::move(pDataSharedPtr)]() {
                      hander(std::move(pDataSharedPtr));
                    });  
                }
                
            });
        }

        app->listen(port, [port](auto *token) {
                if (token) {
                    std::cout << "Listening on port " << port << (SSL ? " with SSL" : "") << std::endl;
                } else {
                    std::cerr << "Failed to listen on port " << port << std::endl;
                }
            })
            .run();
    }

    void registerHttp2(HttpMethod method, const std::string path, std::function<void(std::shared_ptr<HttpData>)> func)
    {
        m_handlers[method][path] = func;
    }

    template <typename F, typename... Args>
    void registerHttp(HttpMethod method, const std::string path, F&& callback, Args&&... args)
    {
         auto boundArgs = std::make_tuple(args...);
        auto boundCallback = [callback, boundArgs](std::shared_ptr<HttpData> data) {
        std::apply([callback, data](Args... args) {
            callback(data, args...);
            }, boundArgs);
        };
        m_handlers[method][path] = boundCallback;
    }

    template <typename F, typename... Args>
    void registerWS(WSMethod method, const std::string path, F&& callback, Args&&... args)
    {
        auto boundArgs = std::make_tuple(args...);
        auto boundCallback = [callback, boundArgs](std::shared_ptr<WsData> data) {
        std::apply([callback, data](Args... args) {
            callback(data, args...);
            }, boundArgs);
        };
        m_wsHanders[path][method] = boundCallback;
    }

    void registerWS2(WSMethod method, const std::string path, std::function<void(std::shared_ptr<WsData>)> func)
    {
      m_wsHanders[path][method] = func;
    }


private:
    void parseQuery2(const std::string &query ,std::unordered_map<std::string, std::string> &queryParams) 
    {
       if(query.length() == 0)
       {
          return;
       }
        size_t pos = 0;
        std::string token;
        std::string key;
        std::string value;
        
        std::string temp_query = query;
        while ((pos = temp_query.find('&')) != std::string::npos) {
            token = temp_query.substr(0, pos);
            size_t eq_pos = token.find('=');
            if (eq_pos != std::string::npos) {
                key = token.substr(0, eq_pos);
                value = token.substr(eq_pos + 1);
                queryParams[key] = value;
            }
            temp_query.erase(0, pos + 1);
        }
        
        size_t eq_pos = temp_query.find('=');
        if (eq_pos != std::string::npos) {
            key = temp_query.substr(0, eq_pos);
            value = temp_query.substr(eq_pos + 1);
            queryParams[key] = value;
        }
    }

    std::unordered_map<std::string, std::string> parseQuery(const std::string &query) {
        std::unordered_map<std::string, std::string> queryParams;
        size_t pos = 0;
        std::string token;
        std::string key;
        std::string value;
        
        std::string temp_query = query;
        while ((pos = temp_query.find('&')) != std::string::npos) {
            token = temp_query.substr(0, pos);
            size_t eq_pos = token.find('=');
            if (eq_pos != std::string::npos) {
                key = token.substr(0, eq_pos);
                value = token.substr(eq_pos + 1);
                queryParams[key] = value;
            }
            temp_query.erase(0, pos + 1);
        }
        
        size_t eq_pos = temp_query.find('=');
        if (eq_pos != std::string::npos) {
            key = temp_query.substr(0, eq_pos);
            value = temp_query.substr(eq_pos + 1);
            queryParams[key] = value;
        }
        
        return queryParams;
    }

    void getCustomHeaders(uWS::HttpRequest *req, std::unordered_map<std::string, std::string> &headers)
    {
        for (auto it = req->begin(); it != req->end(); ++it) 
        {
            headers[std::string((*it).first)] = std::string((*it).second);
        }
    }

private:
    using WSUrlCallbackMap = std::unordered_map<int, std::function<void(std::shared_ptr<WsData>)> >;
    using HttpUrlCallbackMap = std::unordered_map<std::string, std::function<void(std::shared_ptr<HttpData>)> >;
    std::unordered_map<int, HttpUrlCallbackMap> m_handlers;
    std::unordered_map<std::string, WSUrlCallbackMap >m_wsHanders;
    WebBehaviorConfig m_webConfig;
    ObjectPool<HttpDataImpl<SSL>> m_httpObjectPool;
    ObjectPool<WsDataImpl<SSL>> m_wsObjectPool;

};

#endif